import { IStageAssetsInfo, Stage } from "babylon-lib/base/stage";
import { ArcRotateCamera } from "@babylonjs/core/Cameras/arcRotateCamera";
import { Scene } from "@babylonjs/core/scene";
import { Camera } from "@babylonjs/core/Cameras/camera";
import { Light } from "@babylonjs/core/Lights/light";
import { RawAssetsUrl, RawData } from "../raw-assets-info";
import { InitializeComponent } from './default-stage-components/initialize-component';
import { ILoose } from "babylon-lib/tool/utils";
import {
    AbstractAssetTaskInfo, CubeTextureTaskInfo, GLTFMeshTaskInfo
} from "babylon-lib/loader/asset-task-info";
import * as Data from '../data/data';
import { CaptureScreen } from 'babylon-lib/highly-coupled-component/capture-screen';
import { Color4 } from "@babylonjs/core/Maths/math.color";
import { CameraInputPreset } from 'babylon-lib/preset/camera-input-preset';
import { Vector3 } from "babylon-lib/index";
import { Character } from "./default-stage-components/character";
import { HemisphericLight } from '@babylonjs/core/Lights/hemisphericLight'


class DefaultStage extends Stage {

    public get mainScene(): Scene {
        return this.scenes[0];
    }

    public get mainCamera(): ArcRotateCamera {
        return this.camreas[0] as ArcRotateCamera;
    }

    protected assetTaskInfos(): ILoose<AbstractAssetTaskInfo> | Array<IStageAssetsInfo> {
        return Object.assign({}, [
            new GLTFMeshTaskInfo(RawAssetsUrl.modelBuilding),

            new CubeTextureTaskInfo(
                RawAssetsUrl.lightCubePX, RawAssetsUrl.lightCubePY, RawAssetsUrl.lightCubePZ,
                RawAssetsUrl.lightCubeNX, RawAssetsUrl.lightCubeNY, RawAssetsUrl.lightCubeNZ, 0
            )
        ]) as unknown as ILoose<AbstractAssetTaskInfo>;
    }

    public render(): void {
        this.mainScene.render();
        if (Character) Character.update(0.02);
    }

    protected initializeScenes(): Scene[] {
        const scns = super.initializeScenes();
        const scene = scns[0];
        scene.clearColor = new Color4(0, 0, 0, 0);
        return scns;
    }

    protected initializeCameras(scenes: Array<Scene>): Array<Camera> {
        const camera = new ArcRotateCamera('main-camera', 1, 1, 1, new Vector3(0, 0, 0), scenes[0]);
        camera.attachControl(true);
        camera.lowerRadiusLimit = 2;
        camera.upperRadiusLimit = 6;
        camera.lowerBetaLimit = 0.1;
        camera.upperBetaLimit = 1.7;
        camera.wheelPrecision = 100;
        camera.minZ = 0.1;
        camera.maxZ = 1000;
        return [camera];
    }

    protected initializeLights(scenes: Array<Scene>, cameras: Array<Camera>): Array<Light> {
        const hl = new HemisphericLight('hemi-light', new Vector3(1, 1, 1))
        return [hl];
    }

    protected async initializeComponents(scenes: Scene[], cameras: Camera[], lights: Light[]): Promise<void> {

        InitializeComponent.initialize(this);
        CaptureScreen.register(this.engine, this.mainCamera, Data.isProduction.value, RawData.appConfig.name);

        this.bindData();
        Data.cameraData.reset(true);
        new CameraInputPreset(scenes[0]);
    }

    private bindData(): void {
        Data.cameraData.onChange(() => {
            this.mainCamera.alpha = Data.cameraAlpha.value;
            this.mainCamera.beta = Data.cameraBeta.value;
            this.mainCamera.radius = Data.cameraRadius.value;
            this.mainCamera.target = Data.cameraTarget.value;
        });
    }

}


export { DefaultStage };